#include "com_voe_VoEExternalMedia.h"
#include "jni_api.h"
#include "OutputParam.h"
#include "module_common_types.h"
#include "voe_external_media.h"
#include "VoEMediaProcessImpl.h"

static VoEMediaProcessImpl _VoEMediaProcess;

/*
 * Class:     com_voe_VoEExternalMedia
 * Method:    GetInterface
 * Signature: (J)J
 */
JNIEXPORT jlong JNICALL Java_com_voe_VoEExternalMedia_GetInterface
	(JNIEnv* env, jclass cls, jlong p_voiceEngine)
{
	return (jlong)webrtc::VoEExternalMedia::GetInterface((webrtc::VoiceEngine*)p_voiceEngine);
}

/*
 * Class:     com_voe_VoEExternalMedia
 * Method:    Release
 * Signature: (J)I
 */
JNIEXPORT jint JNICALL Java_com_voe_VoEExternalMedia_Release
	(JNIEnv* env, jclass cls, jlong p)
{
	webrtc::VoEExternalMedia* pVoEExternalMedia = (webrtc::VoEExternalMedia*)p;
	return pVoEExternalMedia->Release();
}

/*
 * Class:     com_voe_VoEExternalMedia
 * Method:    RegisterExternalMediaProcessing
 * Signature: (JIILcom/voe/callback/VoEMediaProcess;)I
 */
JNIEXPORT jint JNICALL Java_com_voe_VoEExternalMedia_RegisterExternalMediaProcessing
	(JNIEnv* env, jclass cls, jlong p, jint channel, jint type, jobject obj)
{
	webrtc::VoEExternalMedia* pVoEExternalMedia = (webrtc::VoEExternalMedia*)p;
	if(_VoEMediaProcess.set(env, obj))
	{
		return pVoEExternalMedia->RegisterExternalMediaProcessing(channel, (webrtc::ProcessingTypes)type, _VoEMediaProcess);
	}
	return JCB_Err_Set;
}

/*
 * Class:     com_voe_VoEExternalMedia
 * Method:    DeRegisterExternalMediaProcessing
 * Signature: (JII)I
 */
JNIEXPORT jint JNICALL Java_com_voe_VoEExternalMedia_DeRegisterExternalMediaProcessing
	(JNIEnv* env, jclass cls, jlong p, jint channel, jint type)
{
	webrtc::VoEExternalMedia* pVoEExternalMedia = (webrtc::VoEExternalMedia*)p;
	jint result = pVoEExternalMedia->DeRegisterExternalMediaProcessing(channel, (webrtc::ProcessingTypes)type);
	if(result == 0)
		_VoEMediaProcess.unset(env);
	return result;
}

/*
 * Class:     com_voe_VoEExternalMedia
 * Method:    SetExternalRecordingStatus
 * Signature: (JZ)I
 */
JNIEXPORT jint JNICALL Java_com_voe_VoEExternalMedia_SetExternalRecordingStatus
	(JNIEnv* env, jclass cls, jlong p, jboolean enable)
{
	webrtc::VoEExternalMedia* pVoEExternalMedia = (webrtc::VoEExternalMedia*)p;
	return pVoEExternalMedia->SetExternalRecordingStatus(enable!=0);
}

/*
 * Class:     com_voe_VoEExternalMedia
 * Method:    SetExternalPlayoutStatus
 * Signature: (JZ)I
 */
JNIEXPORT jint JNICALL Java_com_voe_VoEExternalMedia_SetExternalPlayoutStatus
	(JNIEnv* env, jclass cls, jlong p, jboolean enable)
{
	webrtc::VoEExternalMedia* pVoEExternalMedia = (webrtc::VoEExternalMedia*)p;
	return pVoEExternalMedia->SetExternalPlayoutStatus(enable!=0);
}

/*
 * Class:     com_voe_VoEExternalMedia
 * Method:    ExternalRecordingInsertData
 * Signature: (J[SII)I
 */
JNIEXPORT jint JNICALL Java_com_voe_VoEExternalMedia_ExternalRecordingInsertData
  (JNIEnv* env, jclass cls, jlong p, jshortArray speechData10ms, jint samplingFreqHz, jint current_delay_ms)
{
	webrtc::VoEExternalMedia* pVoEExternalMedia = (webrtc::VoEExternalMedia*)p;
	size_t len = (env)->GetArrayLength(speechData10ms);
	short* data = new short[len];
	JniHelper::j2c_shorts(env, speechData10ms, data, len);
	jint result = pVoEExternalMedia->ExternalRecordingInsertData(data, len * sizeof(short), samplingFreqHz, current_delay_ms);
	delete [] data;
	return result;
}

/*
 * Class:     com_voe_VoEExternalMedia
 * Method:    ExternalPlayoutGetData
 * Signature: (J[SIILcom/voe/common/OutputParam;)I
 */
JNIEXPORT jint JNICALL Java_com_voe_VoEExternalMedia_ExternalPlayoutGetData
  (JNIEnv* env, jclass cls, jlong p, jshortArray speechData10ms, jint samplingFreqHz, jint current_delay_ms, jobject obj)
{
	webrtc::VoEExternalMedia* pVoEExternalMedia = (webrtc::VoEExternalMedia*)p;
	int len = (env)->GetArrayLength(speechData10ms);
	short* buf = new short[len];
	int lengthSamples = 0;
	jint result = pVoEExternalMedia->ExternalPlayoutGetData(buf, samplingFreqHz, current_delay_ms, lengthSamples);
	if(result == 0)
	{
		(env)->SetShortArrayRegion(speechData10ms, 0, len, buf);
		JniOutputBuilder job(env);
		OutputParam param(env, obj);
		param.setArray(job.add(lengthSamples).getOutput());
	}
	delete [] buf;
	return result;
}

/*
 * Class:     com_voe_VoEExternalMedia
 * Method:    GetAudioFrame
 * Signature: (JIILcom/voe/common/OutputParam;)I
 */
JNIEXPORT jint JNICALL Java_com_voe_VoEExternalMedia_GetAudioFrame
  (JNIEnv* env, jclass cls, jlong p, jint channel, jint desired_sample_rate_hz, jobject obj)
{
	webrtc::VoEExternalMedia* pVoEExternalMedia = (webrtc::VoEExternalMedia*)p;
	webrtc::AudioFrame audioFrame;
	jint result = pVoEExternalMedia->GetAudioFrame(channel, desired_sample_rate_hz, &audioFrame);
	if(result == 0)
	{
		JniOutputBuilder job(env);
		OutputParam param(env, obj);
		param.setArray(job
			.add(audioFrame.id_)
			.add((int)audioFrame.timestamp_)
			.add((short*)audioFrame.data_, sizeof(audioFrame.data_)/sizeof(int16_t))
			.add(audioFrame.samples_per_channel_)
			.add(audioFrame.sample_rate_hz_)
			.add(audioFrame.num_channels_)
			.add((int)audioFrame.speech_type_)
			.add((int)audioFrame.vad_activity_)
			.add((int)audioFrame.energy_)
			.getOutput());
	}
	return result;
}

/*
 * Class:     com_voe_VoEExternalMedia
 * Method:    SetExternalMixing
 * Signature: (JIZ)I
 */
JNIEXPORT jint JNICALL Java_com_voe_VoEExternalMedia_SetExternalMixing
	(JNIEnv* env, jclass cls, jlong p, jint channel, jboolean enable)
{
	webrtc::VoEExternalMedia* pVoEExternalMedia = (webrtc::VoEExternalMedia*)p;
	return pVoEExternalMedia->SetExternalMixing(channel, enable!=0);
}

